package com.cyanite.playlv2;

import com.cyanite.playlv2api.PlayLv2Api;
import com.cyanite.playlv2api.error.PlayLv2ApiException;
import com.cyanite.playlv2api.types.Settings;
import com.cyanite.playlv2api.types.User;
import com.cyanite.playlv2.R;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Lets the user set pings on/off for a given friend.
 *
 *
 */
public class UserDetailsPingsActivity extends Activity {

    public static final String EXTRA_USER_PARCEL = PlayLv2.PACKAGE_NAME
        + ".UserDetailsPingsActivity.EXTRA_USER_PARCEL";

    public static final String EXTRA_USER_RETURNED = PlayLv2.PACKAGE_NAME
        + ".UserDetailsPingsActivity.EXTRA_USER_RETURNED";

    private StateHolder mStateHolder;


    private BroadcastReceiver mLoggedOutReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            finish();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.user_details_pings_activity);
        registerReceiver(mLoggedOutReceiver, new IntentFilter(PlayLv2.INTENT_ACTION_LOGGED_OUT));

        mStateHolder = new StateHolder();
        if (getIntent().getExtras() != null) {
            if (getIntent().hasExtra(EXTRA_USER_PARCEL)) {
                User user = getIntent().getExtras().getParcelable(EXTRA_USER_PARCEL);
                mStateHolder.setUser(user);
            } else {
                finish();
                return;
            }
        } else {
            finish();
            return;
        }

        ensureUi();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mLoggedOutReceiver);
    }

    @Override
    public Object onRetainNonConfigurationInstance() {
        mStateHolder.setActivity(null);
        return mStateHolder;
    }

    private void ensureUi() {
        User user = mStateHolder.getUser();

        TextView tv = (TextView)findViewById(R.id.userDetailsPingsActivityDescription);
        Button btn = (Button)findViewById(R.id.userDetailsPingsActivityButton);

        if (user.getSettings().getGetPings()) {
            tv.setText(getString(R.string.user_details_pings_activity_description_on,
                    user.getUserName()));
            btn.setText(getString(R.string.user_details_pings_activity_pings_off,
                    user.getUserName()));
            btn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    v.setEnabled(false);
                    setProgressBarIndeterminateVisibility(true);
                    mStateHolder.startPingsTask(UserDetailsPingsActivity.this, false);
                }
            });
        } else {
            tv.setText(getString(R.string.user_details_pings_activity_description_off,
                    user.getUserName()));
            btn.setText(getString(R.string.user_details_pings_activity_pings_on,
                    user.getUserName()));
            btn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    v.setEnabled(false);
                    setProgressBarIndeterminateVisibility(true);
                    mStateHolder.startPingsTask(UserDetailsPingsActivity.this, true);
                }
            });
        }

        if (mStateHolder.getIsRunningTaskPings()) {
            btn.setEnabled(false);
            setProgressBarIndeterminateVisibility(true);
        } else {
            btn.setEnabled(true);
            setProgressBarIndeterminateVisibility(false);
        }
    }

    private void setPreparedResultIntent() {
        if (mStateHolder.getPreparedResult() != null) {
            setResult(Activity.RESULT_OK, mStateHolder.getPreparedResult());
        }
    }

    private void prepareResultIntent() {
        Intent intent = new Intent();
        intent.putExtra(EXTRA_USER_RETURNED, mStateHolder.getUser());
        mStateHolder.setPreparedResult(intent);
        setPreparedResultIntent();
    }

    private void onTaskPingsComplete(Settings settings, String userId, boolean on, Exception ex) {
        mStateHolder.setIsRunningTaskPings(false);

        // The api is returning pings = false for all cases, so manually overwrite,
        // assume a non-null settings object is success.
        if (settings != null) {
            settings.setGetPings(on);
            mStateHolder.setSettingsResult(settings);
            prepareResultIntent();

        } else {
            Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG).show();
        }

        ensureUi();
    }

    private static class TaskPings extends AsyncTask<Void, Void, Settings> {
        private UserDetailsPingsActivity mActivity;
        private String mUserId;
        private boolean mOn;
        private Exception mReason;

        public TaskPings(UserDetailsPingsActivity activity, String userId, boolean on) {
            mActivity = activity;
            mUserId = userId;
            mOn = on;
        }

        public void setActivity(UserDetailsPingsActivity activity) {
            mActivity = activity;
        }

        @Override
        protected void onPreExecute() {
            mActivity.ensureUi();
        }

        @Override
        protected Settings doInBackground(Void... params) {
            try {
                PlayLv2 playlv2 = (PlayLv2) mActivity.getApplication();
                PlayLv2Api playlv2api = playlv2.getPlayLv2Api();

                return playlv2api.setpings(mUserId, mOn);

            } catch (Exception ex) {
                mReason = ex;
            }

            return null;
        }

        @Override
        protected void onPostExecute(Settings settings) {
            if (mActivity != null) {
                mActivity.onTaskPingsComplete(settings, mUserId, mOn, mReason);
            }
        }

        @Override
        protected void onCancelled() {
            if (mActivity != null) {
                mActivity.onTaskPingsComplete(null, mUserId, mOn, new PlayLv2ApiException("Tip task cancelled."));
            }
        }
    }

    private static class StateHolder {
        private User mUser;
        private boolean mIsRunningTask;
        private Intent mPreparedResult;
        private TaskPings mTaskPings;


        public StateHolder() {
            mPreparedResult = null;
            mIsRunningTask = false;
        }

        public User getUser() {
            return mUser;
        }

        public void setUser(User user) {
            mUser = user;
        }

        public void setSettingsResult(Settings settings) {
            mUser.getSettings().setGetPings(settings.getGetPings());
        }

        public void startPingsTask(UserDetailsPingsActivity activity, boolean on) {
            if (!mIsRunningTask) {
                mIsRunningTask = true;
                mTaskPings = new TaskPings(activity, mUser.getId(), on);
                mTaskPings.execute();
            }
        }

        public void setActivity(UserDetailsPingsActivity activity) {
            if (mTaskPings != null) {
                mTaskPings.setActivity(activity);
            }
        }

        public void setIsRunningTaskPings(boolean isRunning) {
            mIsRunningTask = isRunning;
        }

        public boolean getIsRunningTaskPings() {
            return mIsRunningTask;
        }

        public Intent getPreparedResult() {
            return mPreparedResult;
        }

        public void setPreparedResult(Intent intent) {
            mPreparedResult = intent;
        }
    }
}
